//
//  HttpDownloadManager.m
//  Etion
//
//  Created by  user on 11-3-22.
//  Copyright 2011 GuangZhouXuanWu. All rights reserved.
//

#import "XLGDownloadManager.h"

#import "XLGDownloadManagerInternal.h"

#import "XLGDownloadHttpOperation.h"

#import "XLGDownloadSocketOperation.h"

#import "XLGDownloadDBOperation.h"

#import "XLGDownloadManagerInternalDelegate.h"

#import "XLGDownloadPool.h"

#define HTTPDOWNLOADSUSPENDTAG  @"suspend"

NSString *const XLGDownloadManagerDownloadFinished = @"XLGDownloadManagerDownloadFinished";

NSString *const XLGDownloadManagerBackgroundMaintainKey = @"XLGDownloadManagerBackgroundMaintainKey";

NSString *const XLGDownloadDBFile = @"Download.db";

NSString *const XLGDownloadDataFolder = @"DownloadData";

@interface XLGDownloadManager()<CBackgroundMaintainDelegate,XLGDownloadManagerInternalDelegate>
{
    XLGDownloadPool *_pool;
    
    NSMutableArray *_arOperationDelegate;
    
    NSCondition *_scanCondition;
    BOOL _bScanloop;
    NSThread *_scanThread;
    
    BOOL _bRunning;
}

@end

@implementation XLGDownloadManager

-(id)init
{
	self = [super init];
	
    _commonindex = [[XLGDownloadDBOperation alloc]initWithTablePath:[[XLGContext context].m_szUserdefaulteppath stringByAppendingPathComponent:XLGDownloadDBFile]];
	
	_pool = [XLGDownloadPool new];
    _pool.maxCount = 2;
    
    _arOperationDelegate = [NSMutableArray new];
    
    _dlingIndexQueue = [[XMSDispatchQueueWrapper alloc]initWithName:""];
    _operationDelegateQueue = [[XMSDispatchQueueWrapper alloc]initWithName:""];
    
	return self;
}

-(void)dealloc
{
    [_dlingIndexQueue release_mm];
    [_operationDelegateQueue release_mm];
	_bScanloop=NO;
    [_scanCondition signal];
    [_scanCondition release_mm];
    [_scanThread release_mm];
	[_pool release_mm];
	[_arDlingindex release_mm];
	_arDlingindex=nil;
	[_commonindex release_mm];
    [_arOperationDelegate release_mm];
	superdealloc_mm;
}

-(void)addDownloadManagerDelegate:(id<XLGDownloadManagerDelegate>)delegate
{
    [_operationDelegateQueue dispatchThreadSync:^
    {
        if(NO==[_arOperationDelegate containsObject:delegate])
            [_arOperationDelegate addObject:delegate];
    }];
}

-(void)removeDownloadManagerDelegate:(id<XLGDownloadManagerDelegate>)delegate
{
    [_operationDelegateQueue dispatchThreadSync:^
    {
        if(YES==[_arOperationDelegate containsObject:delegate])
            [_arOperationDelegate removeObject:delegate];
    }];
}

- (void)addDownloaingOperationDelegate:(id<XLGDownloadOperationDelegate>)delegate
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        for(XLGDownloadOperation* ho in _arDlingindex)
        {
            [ho addOperationDelegate:delegate];
        }
    }];
}

- (void)removeDownloadingOperationDelegate:(id<XLGDownloadOperationDelegate>)delegate
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        for(XLGDownloadOperation* ho in _arDlingindex)
        {
            [ho removeOperationDelegate:delegate];
        }
    }];
}

- (void)removeDownloaingOperationDelegate:(NSDictionary*)dictionary
{
    if(dictionary.count <= 0)
        return;
    [_dlingIndexQueue dispatchThreadSync:^
    {
        for(NSString *szUrl in [dictionary allKeys])
        {
            for(XLGDownloadOperation* ho in _arDlingindex)
            {
                if(YES == [ho.mi.URL isEqualToString:szUrl])
                {
                    [ho removeOperationDelegate:[dictionary objectForKey:szUrl]];
                    break;
                }
            }
        }
    }];
}

- (void)removeDownloaingOperationDelegateWithURLs:(NSArray *)arUrl
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        for(NSString *szUrl in arUrl)
        {
             for(XLGDownloadOperation* ho in _arDlingindex)
             {
                 if(YES == [ho.mi.URL isEqualToString:szUrl])
                 {
                     [ho removeAllOperationdelegate];
                     break;
                 }
             }
        }
    }];
}

- (void)removeDownloadingAllOperationDelegate
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        for(XLGDownloadOperation* ho in _arDlingindex)
        {
            [ho removeAllOperationdelegate];
        }
    }];
}

-(NSUInteger)downloadingCount
{
    __block NSUInteger count = 0;
    [_dlingIndexQueue dispatchThreadSync:^
    {
        count = _arDlingindex.count;
    }];
    return count;
}

-(void)setMaxDownloadingIndex:(NSUInteger)maxDownloadingIndex
{
    _pool.maxCount = maxDownloadingIndex;
}

-(NSUInteger)maxDownloadingIndex
{
    return _pool.maxCount;
}

-(void)exchangeDownloadItemStatus:(XLGDownloadIndex*)downloadIndex
{
    XLGDownloadIndex *index = [XLGDownloadIndex downloadIndexWithWithDownloadIndex:downloadIndex];
    [_operationDelegateQueue dispatchThreadAsync:^
    {
        for (NSUInteger i = 0; i < _arOperationDelegate.count; i++)
{
            id<XLGDownloadManagerDelegate> obj = [_arOperationDelegate objectAtIndex:i];
            [obj downloadManager:self exchangeDownloadIndex:index];
        }
    }];
}

//-(void)AddDownloadIndexByFsfile:(CFsfilesObj*)fsfile target:(id<XLGDownloadOperationDelegate>)target complete:(void (^)(int))complete
//{
//    [self addDownloadTaskWithTarget:target index:^(CMessageInstanceObj *mi)
//    {
//        mi.m_extendid=[XMSGUID GUIDBytesWithGUIDString:fsfile.m_szFileid];
//        mi.m_szTitle=fsfile.m_szFilename;
//        mi.m_szContent=[self FsfileToMessageInstanceObjContent:fsfile];
//        mi.m_sendtime=fsfile.m_uploadtime;
//        mi.m_nEnterprisenumber=fsfile.m_nEnterprisenumber;
//        mi.m_nTargettype=EDownloadSourceTypeDOWNLOADCTRL;
//        mi.m_nImportant=EDownloadOperationChannelTypeSOCKET;
//    } complete:complete];
//}

- (void)addDownloadTaskWithOperationDelegate:(id <XLGDownloadOperationDelegate>)target index:(void (^)(XLGDownloadIndex *mi))mi asyncCompletion:(void (^)(NSInteger nResult))completion
{
    XLGDownloadIndex* mii = [[XLGDownloadIndex new] autorelease_mm];
	mii.targetType = XLGDownloadTargetTypeDownload;
	mii.submitTime = [NSDate date];
	mii.downloadTime = [NSDate date];
	mii.downloadStatus = XLGDownloadStatusTypeWaiting;
    mi(mii);
    mii.extendID = [XMSGUID GUIDString];
	[self addDownloadTaskWithIndex:mii operationDelegate:target asyncCompletion:completion];
}

- (void)addDownloadTaskWithTaskName:(NSString *)taskName URL:(NSString *)szUrl operationDelegate:(id <XLGDownloadOperationDelegate>)delegate asyncCompletion:(void (^)(NSInteger nResult))completion
{
    [self addDownloadTaskWithSourceType:EDownloadSourceTypeDOWNLOADCTRL taskName:taskName URL:szUrl operationDelegate:delegate asyncCompletion:completion];
}

- (void)addDownloadTaskWithSourceType:(EDownloadSourceType)sourcetype taskName:(NSString *)taskName URL:(NSString *)szUrl operationDelegate:(id <XLGDownloadOperationDelegate>)delegate asyncCompletion:(void (^)(NSInteger nResult))completion
{
   	XLGDownloadIndex* mi = [[XLGDownloadIndex new] autorelease_mm];
	mi.extendID = [XMSGUID GUIDString];
	mi.title = taskName;
	mi.URL = szUrl;
	mi.targetType = XLGDownloadTargetTypeDownload;
	mi.submitTime = [NSDate date];
	mi.downloadTime = [NSDate date];
	mi.downloadStatus = XLGDownloadStatusTypeWaiting;
    mi.sourceType = sourcetype;
    mi.channelType = XLGDownloadOperationChannelTypeHTTP;
	[self addDownloadTaskWithIndex:mi operationDelegate:delegate asyncCompletion:completion];
}

- (void)addDownloadTaskWithIndex:(XLGDownloadIndex *)mi operationDelegate:(id <XLGDownloadOperationDelegate>)target asyncCompletion:(void (^)(NSInteger nResult))completion
{
    DispatchThread(^
    {
        [self addDownloadTaskWithIndex:mi operationDelegate:target completion:completion];
    });
}

- (void)addDownloadTaskWithIndex:(XLGDownloadIndex *)mi operationDelegate:(id <XLGDownloadOperationDelegate>)target completion:(void (^)(NSInteger nResult))completion
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        XLGDownloadOperation *findIndex = nil;
        for(XLGDownloadOperation* o in _arDlingindex)
        {
            XLGDownloadIndex* mii = o.mi;
            if([mi.URL isEqualToString:mii.URL] == YES)
            {
/*
#ifdef DEBUG
                    for(XLGDownloadOperation* o in _arDlingindex)
                    {
                        XLGDownloadIndex* mi=o._mi;
                        NSLog(@"adddownloadindex--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
                    }
#endif
*/
                if(mii.downloadStatus == XLGDownloadStatusTypeDownloading || mii.downloadStatus == XLGDownloadStatusTypeWaiting)
                {
                    if(completion != NULL)
                        completion(NO);
                    return;
                }
                else
                {
                    findIndex = o;
                    break;
                }
            }
        }
        
        __block NSInteger i = 0;
        for (i = _arDlingindex.count - 1; i >= 0; i--)
        {
            XLGDownloadIndex *mi = ((XLGDownloadOperation *)_arDlingindex[i]).mi;
            XLGDownloadStatusType sendStatus = mi.downloadStatus;
            if (XLGDownloadStatusTypeStop != sendStatus &&
                XLGDownloadStatusTypeFailed != sendStatus)
            {
                i++;
                break;
            }
        }
        i = MAX(0, i);
        
        XLGDownloadIndex* mii = nil;
        
        if(findIndex != nil)
        {
            [[findIndex retain_mm] autorelease_mm];
            
            mii = findIndex.mi;
            
            NSUInteger nIndex = mii.serialNo;
            mii.downloadStatus = XLGDownloadStatusTypeWaiting;
            mii.serialNo = i;
    
            [findIndex addOperationDelegate:target];
            
            [_arDlingindex removeObjectAtIndex:nIndex];
            [_arDlingindex insertObject:findIndex atIndex:mii.serialNo];
        }
        else
        {
            mii = mi;
            
            mi.downloadStatus = XLGDownloadStatusTypeWaiting;
            mi.serialNo = i;
            
            XLGDownloadOperation* o = [self initDownloadOperationChannel:mi];
            
            [o addOperationDelegate:target];
            [_arDlingindex insertObject:o atIndex:mi.serialNo];
            
            [_commonindex addDownloadIndex:mi];
        }
        
        [_commonindex modifyDownloadIndexStatus:^NSInteger(NSInteger(^modify)(NSUInteger serialNo,NSString* extendID,XLGDownloadStatusType status))
        {
             NSInteger nResult = FALSE;
             for (; i < _arDlingindex.count; i++)
             {
                 XLGDownloadIndex *mi = ((XLGDownloadOperation *)_arDlingindex[i]).mi;
                 mi.serialNo = i;
                 nResult =  modify(i,mi.extendID,mi.downloadStatus);
                 if(nResult != YES)
                     break;
             }
             return nResult;
        }];
            
/*
#ifdef DEBUG
            for(XLGDownloadOperation* o in _arDlingindex)
            {
                CMessageInstanceObj* mi=o._mi;
                NSLog(@"adddownloadindex--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
            }
            NSMutableArray* ar=nil;
            [self getDownloadIndexs:EDownloadIndexTypeDOWNLOADING mi:&ar];
            for(CMessageInstanceObj* mi in ar)
                NSLog(@"databaseadddownloadindex--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
            [ar release_mm];
            
            NSLog(@"adddownloadindex");
            NSLog(@"_downloadingRange.location:%d,_downloadingRange.length:%d",_downloadingRange.location,_downloadingRange.length);
            NSLog(@"_waitingRange.location:%d,_waitingRange.length:%d",_waitingRange.location,_waitingRange.length);
            NSLog(@"_stopRange.location:%d,_stopRange.length:%d",_stopRange.location,_stopRange.length);
            NSLog(@"_failedRange.location:%d,_failedRange.length:%d",_failedRange.location,_failedRange.length);
#endif
*/
        [self exchangeDownloadItemStatus:mii];
        
        [self openScanThread];
        
        if(completion != NULL)
            completion(YES);
    }];
}

-(NSInteger)deleteDownloadItem:(NSUInteger)nIndex withOperation:(XLGDownloadOperation*)o
{
	XLGDownloadIndex* mi = o.mi;
	NSString* extendID = [[mi.extendID retain_mm] autorelease_mm];
	XLGDownloadStatusType downloadStatus = mi.downloadStatus;
	switch(downloadStatus)
	{
		case XLGDownloadStatusTypeDownloading:
		{
			[o stopDownload];
			break;
		}
        default:
        {
            break;
        }
	}
	
    [_arDlingindex removeObjectAtIndex:nIndex];
    
    __block NSUInteger i = nIndex;
    [_commonindex modifyDownloadIndexStatus:^NSInteger(NSInteger(^modify)(NSUInteger serialNo,NSString* extendID,XLGDownloadStatusType status))
    {
         NSInteger nResult = FALSE;
         for (; i < _arDlingindex.count; i++)
         {
             XLGDownloadIndex *mi = ((XLGDownloadOperation *)_arDlingindex[i]).mi;
             mi.serialNo = nIndex;
             nResult =  modify(i,mi.extendID,mi.downloadStatus);
             if(nResult != YES)
                 break;
         }
         return nResult;
    }];
    
	NSString* filename = [mi.URL lastPathComponent];
	[XMSFileHelper deleteFileDir:[NSString stringWithFormat:@"%@/%@.%@",[self defaultStorePath],filename,[filename pathExtension]]];
    
    return [_commonindex deleteIndexWithExtendID:@[extendID]];
}

/*
-(int)DeleteDownloadingIndex:(int)nIndex
{
	int nResult=-1;
	[m_dlingindexlock lock];
	if(nIndex<_arDlingindex.count)
	{
		XLGDownloadOperation* o=[_arDlingindex objectAtIndex:nIndex];
		[self deleteDownloadItem:nIndex withOperation:o];
	
		nResult=YES;
				
#ifdef DEBUG
		for(XLGDownloadOperation* o in _arDlingindex)
		{
			CMessageInstanceObj* mi=o._mi;
			NSLog(@"deleteddownloadindex--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
		}
		
		NSMutableArray* ar=nil;
		[self getDownloadIndexs:EDownloadIndexTypeDOWNLOADING mi:&ar];
		for(CMessageInstanceObj* mi in ar)
			NSLog(@"deletescanddownloadindex--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
		[ar release_mm];
		
		NSLog(@"deleteddownloadindex");
		NSLog(@"_downloadingRange.location:%d,_downloadingRange.length:%d",_downloadingRange.location,_downloadingRange.length);
		NSLog(@"_waitingRange.location:%d,_waitingRange.length:%d",_waitingRange.location,_waitingRange.length);
		NSLog(@"_stopRange.location:%d,_stopRange.length:%d",_stopRange.location,_stopRange.length);
		NSLog(@"_failedRange.location:%d,_failedRange.length:%d",_failedRange.location,_failedRange.length);
#endif
		
	}
	[m_dlingindexlock unlock];
	return nResult;
}
*/

- (void)deleteDownloadItemWithCondition:(NSArray*)arCondition compare:(BOOL(^)(id condition,XLGDownloadIndex* mi))compare completion:(void(^)(NSArray *arResult))completion
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        NSMutableArray *arResult = [[NSMutableArray new]autorelease_mm];
        for(id condition in arCondition)
        {
            for(NSUInteger nIndex = 0;nIndex < _arDlingindex.count; nIndex++)
            {
                XLGDownloadOperation* o = _arDlingindex[nIndex];
                XLGDownloadIndex* mi = o.mi;
                if(compare(condition,mi)==YES)
                {
                    [[mi retain_mm]autorelease_mm];
                    
                    [self deleteDownloadItem:nIndex withOperation:o];
                    
                    XLGDownloadIndex* mii = [[XLGDownloadIndex new]autorelease_mm];
                    mii.downloadStatus = XLGDownloadStatusTypeDelete;
                    mii.extendID = mi.extendID;
                    mii.URL = mi.URL;
                    
                    [self exchangeDownloadItemStatus:mii];
        
                    [arResult addObject:condition];
                    
                    break;
                }
            }
        }
        completion(arResult);
    }];
}

- (void)deleteDownloadItemWithURLs:(NSArray *)arURL asyncCompletion:(void (^)(NSArray *))completion
{
    DispatchThread(^
    {
        if(arURL.count > 0)
        {
            [self deleteDownloadItemWithCondition:arURL compare:^BOOL(id condition, XLGDownloadIndex *mi)
            {
                return [mi.URL isEqualToString:(NSString*)condition];
            } completion:completion];
        }
        else
            completion(nil);
    });
}

- (void)deleteDownloadItemWithExtendIDs:(NSArray *)arExtendids asyncCompletion:(void (^)(NSArray *))completion
{
    DispatchThread(^
    {
        if(arExtendids.count >0)
        {
            [self deleteDownloadItemWithCondition:arExtendids compare:^BOOL(id condition, XLGDownloadIndex *mi)
            {
                return [mi.extendID isEqualToString:(NSString*)condition];
            } completion:completion];
        }
        else
            completion(nil);
    });
}


-(void)openScanThread
{
	if(YES == [XLGContext context].m_bIsoffline)
		return;
	if(_scanThread == nil)
    {
        _bScanloop=YES;
        _scanThread = [[NSThread alloc]initWithTarget:self selector:@selector(scanDownloadIndex) object:nil];
        [_scanThread start];
    }
    else
        [_scanCondition signal];
}

-(void)scanDownloadIndex
{
    @autoreleasepool
    {
        if(nil == _scanCondition)
            _scanCondition = [NSCondition new];
        
        while(YES == _bScanloop)
        {
            @autoreleasepool
            {
                __block BOOL b = NO;
                __block NSUInteger nDlingindex = 0;
                
                [_dlingIndexQueue dispatchThreadSync:^
                {
/*
#ifdef DEBUG
                    NSLog(@"scanddownloadindex!!!--queueoperation--%i",[_queue operationCount]);
#endif
*/
                    if(_pool.currentCount < _pool.maxCount)
                    {
                        @autoreleasepool
                        {
                            for(XLGDownloadOperation* o in _arDlingindex)
                            {
                                XLGDownloadIndex* mi = o.mi;
                                if(XLGDownloadStatusTypeWaiting == mi.downloadStatus)
                                {
                                    b = YES;
                                    
                                    mi.downloadStatus = XLGDownloadStatusTypeDownloading;
                                    
                                    [self exchangeDownloadItemStatus:mi];
                                    
/*
#ifdef DEBUG
                                    for(XLGDownloadOperation* oo in _arDlingindex)
                                    {
                                        CMessageInstanceObj* mi=oo._mi;
                                        NSLog(@"scanddownloadindex--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
                                    }
                                    
                                    NSMutableArray* ar=nil;
                                    [self getDownloadIndexs:EDownloadIndexTypeDOWNLOADING mi:&ar];
                                    for(CMessageInstanceObj* mi in ar)
                                        NSLog(@"databasescanddownloadindex--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
                                    [ar release_mm];
                                    
                                    NSLog(@"scanddownloadindex");
                                    NSLog(@"_downloadingRange.location:%d,_downloadingRange.length:%d",_downloadingRange.location,_downloadingRange.length);
                                    NSLog(@"_waitingRange.location:%d,_waitingRange.length:%d",_waitingRange.location,_waitingRange.length);
                                    NSLog(@"_stopRange.location:%d,_stopRange.length:%d",_stopRange.location,_stopRange.length);
                                    NSLog(@"_failedRange.location:%d,_failedRange.length:%d",_failedRange.location,_failedRange.length);
#endif
*/
                                    [_pool addDownloadOperation:o];
                                }
                                
                                if(_pool.currentCount >= _pool.maxCount)
                                    break;
                            }
                        }
                    }
                    else
                        b = YES;
/*
#ifdef DEBUG
                    NSLog(@"scanddownloadindex!!!--endscanddownloadindex--");
#endif
*/
                    nDlingindex = _arDlingindex.count;
                }];

                if(nDlingindex <= 0 || NO == b)
                {
                    [_scanCondition lock];
                    [_scanCondition wait];
                    [_scanCondition unlock];
                }
                else
                {
                    [_scanCondition lock];
                    NSDate* sleepdate = [[NSDate alloc]initWithTimeIntervalSinceNow:1];
                    [_scanCondition waitUntilDate:sleepdate];
                    [sleepdate release_mm];
                    [_scanCondition unlock];
                }
            }
        }
        [_scanCondition release_mm];
        _scanCondition = nil;
    }
}

-(void)initDownloadingIndexs
{
	[_arDlingindex release_mm];
	_arDlingindex = [NSMutableArray new];
    
	NSMutableArray* ar = [[NSMutableArray new]autorelease_mm];
	
    [_commonindex getDownloadIndexCompletion:^(NSInteger nResult, NSArray *index)
    {
        [ar addObjectsFromArray:index];
    }];
    
    [_commonindex modifyDownloadIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger serialNo,NSString* extendID,XLGDownloadStatusType status))
    {
        NSInteger nResult = FALSE;
        for(XLGDownloadIndex* mi in ar)
        {
            switch(mi.downloadStatus)
            {
                case XLGDownloadStatusTypeNextContinue:
                {
                    mi.downloadStatus = XLGDownloadStatusTypeWaiting;
                    nResult = modify(mi.serialNo,mi.extendID,mi.downloadStatus);
                    break;
                }
                default:
                {
                    nResult = YES;
                    break;
                }
            }
            if(nResult != YES)
                break;
        }
        return nResult;
    }];
    
	for(XLGDownloadIndex* mi in ar)
	{
		XLGDownloadOperation* o = [self initDownloadOperationChannel:mi];

		[_arDlingindex addObject:o];
	}
	
/*
#ifdef DEBUG
	for(XLGDownloadOperation* o in _arDlingindex)
	{
		CMessageInstanceObj* mi=o._mi;
		NSLog(@"downloadagain--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
	}
	
	NSLog(@"downloadagain");
	NSLog(@"_downloadingRange.location:%d,_downloadingRange.length:%d",_downloadingRange.location,_downloadingRange.length);
	NSLog(@"_waitingRange.location:%d,_waitingRange.length:%d",_waitingRange.location,_waitingRange.length);
	NSLog(@"_stopRange.location:%d,_stopRange.length:%d",_stopRange.location,_stopRange.length);
	NSLog(@"_failedRange.location:%d,_failedRange.length:%d",_failedRange.location,_failedRange.length);
#endif
*/
    
	if(YES==[XLGContext context].m_bIsoffline)
		return;
    
    if(YES==[XLGContext context].m_bIsofflinelogin)
        return;
	
    if(_arDlingindex.count>0)
        [self openScanThread];
    
    _bRunning=YES;
}

-(void)releaseDownloadManager
{
    _bRunning = NO;
	_bScanloop = NO;
    [_scanCondition signal];
    [_scanThread release_mm];
    _scanThread = nil;
	[self stopDownload:nil];
}

-(void)suspendDownloadManager
{
    _bRunning = NO;
	_bScanloop = NO;
    [_scanCondition signal];
    [_scanThread release_mm];
    _scanThread = nil;
	[self stopDownload:HTTPDOWNLOADSUSPENDTAG];
}

-(BOOL)resumeDownloadManger
{
	if(YES==[XLGContext context].m_bIsoffline)
		return NETWORKOFFLINE;
    
    if(YES==[XLGContext context].m_bIsofflinelogin)
        return NETWORKOFFLINE;
    
    if(_bRunning == YES)
        return YES;
    
    _bRunning = YES;
	
	for(XLGDownloadOperation* o in _arDlingindex)
	{
		if(XLGDownloadStatusTypeNextContinue == o.mi.downloadStatus)
			o.mi.downloadStatus = XLGDownloadStatusTypeWaiting;
	}
    
    if(_arDlingindex.count>0)
        [self openScanThread];
	
	return YES;
}

- (void)getIndex:(XLGDownloadTargetType)targetType withSourceType:(NSUInteger)sourceType completion:(void (^)(NSInteger nResult, NSArray *index))completion
{
    [_commonindex getIndex:targetType withSourceType:sourceType completion:completion];
}

- (void)getFinishedIndexsAsyncCompletion:(void(^)(NSInteger nResult,NSArray *arIndex))completion
{
    DispatchThread(^
    {
        [_commonindex getFinishedIndexCompletion:completion];
    });
}

- (void)resumeDownloadWithURLs:(NSArray *)arUrl operationDelegate:(id<XLGDownloadOperationDelegate>)operationDelegate asyncCompletion:(void(^)(NSArray *arResult))completion
{
    DispatchThread(^
    {
        [_dlingIndexQueue dispatchThreadSync:^
        {
            NSMutableArray *resume = [[NSMutableArray new] autorelease_mm];
            NSMutableArray *tmp = [arUrl mutableCopy];
            for(NSString *URL in arUrl)
            {
                [self enumDownloadingItem:^(NSUInteger nIndex, XLGDownloadIndex *downloadingItem, BOOL *bStop)
                {
                    if([downloadingItem.URL isEqualToString:URL] == YES && (downloadingItem.downloadStatus == XLGDownloadStatusTypeFailed || downloadingItem.downloadStatus == XLGDownloadStatusTypeStop))
                    {
                        *bStop = YES;
                        [tmp addObject:URL];
                        [resume addObject:downloadingItem];
                    }
                }];
            }
            
            for(XLGDownloadIndex *index in resume)
            {
                if([operationDelegate respondsToSelector:@selector(refreshDownloadOperationItem:percentWithFileTotalSize:downloadedSize:)])
                {
                    [(id<XLGDownloadOperationDelegate>)operationDelegate downloadOperationItem:index.extendID refreshPercentWithFileTotalSize:index.totalByte downloadedSize:index.downloadByte];
                }
                
                [self addDownloadTaskWithIndex:index operationDelegate:operationDelegate completion:^(NSInteger nResult)
                {
                }];
            }
            if(completion != NULL)
                completion(tmp);
        }];
    });
}

- (void)redownloadFinishedTaskWithURLs:(NSArray *)arUrl operationDelegate:(id<XLGDownloadOperationDelegate>)operationDelegate asyncCompletion:(void(^)(NSArray *arResult))completion
{
    DispatchThread(^
    {
        [_dlingIndexQueue dispatchThreadSync:^
        {
            NSMutableArray *redownloadIndex = [[NSMutableArray new] autorelease_mm];
            NSMutableArray *tmp = [arUrl mutableCopy];
            /*
            for(NSString *URL in arUrl)
            {
                [self enumDownloadingItem:^(NSUInteger nIndex, XLGDownloadOperation *downloadingItem, BOOL *bStop)
                {
                     if([downloadingItem.mi.content isEqualToString:URL] == YES)
                     {
                         *bStop = YES;
                         [redownloadIndex addObject:downloadingItem.mi];
                         [tmp removeObject:URL];
                         [self deleteDownloadItem:nIndex withOperation:downloadingItem];
                     }
                }];
            }
            */
            
            [_commonindex getIndexWithURLs:arUrl completion:^(NSInteger nResult, NSArray *index)
            {
                [redownloadIndex addObjectsFromArray:index];
            }];
            
            for(XLGDownloadIndex *index in redownloadIndex)
            {
                NSString *URL = index.URL;
             //   [_commonindex deleteIndexWithURLs:@[URL]];
                [self deleteFile:[URL lastPathComponent]];
                
                index.downloadStatus = XLGDownloadStatusTypeWaiting;
                index.targetType = XLGDownloadTargetTypeDownload;
                index.serialNo = 0;
                index.totalByte = 0;
                index.downloadByte = 0;

                if([operationDelegate respondsToSelector:@selector(refreshDownloadOperationItem:percentWithFileTotalSize:downloadedSize:)])
                {
                    [(id<XLGDownloadOperationDelegate>)operationDelegate downloadOperationItem:index.extendID refreshPercentWithFileTotalSize:index.totalByte downloadedSize:index.downloadByte];
                }
            
                [self addDownloadTaskWithIndex:index operationDelegate:operationDelegate completion:^(NSInteger nResult)
                {
                }];
            
                [tmp addObject:URL];
            }
            if(completion != NULL)
                completion(tmp);
        }];
    });
}

- (void)stopDownloadItemWithURLs:(NSArray *)arURL operationDelegate:(id <XLGDownloadOperationDelegate>)target asyncCompletion:(void(^)(NSArray *arResult))completion
{
    DispatchThread(^
    {
        [_dlingIndexQueue dispatchThreadSync:^
        {
            NSMutableArray *arResult = [[NSMutableArray new]autorelease_mm];
            for(NSString *url in arURL)
            {
                for(XLGDownloadOperation* o in _arDlingindex)
                {
                    if(YES == [o.mi.URL isEqualToString:url])
                    {
//                        if(EDownloadSourceTypeDATASOURCE == mi.targetType)
//                        {
//                            mi = nil;
//                            break;
//                        }
/*
#ifdef DEBUG
                        NSLog(@"stopdownload!!!--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
#endif
*/
                        [[o retain_mm] autorelease_mm];
                        
                        XLGDownloadIndex* mi = o.mi;
                        NSUInteger i = 0;
                        for (; i < _arDlingindex.count; i++)
                        {
                            XLGDownloadIndex *mm = ((XLGDownloadOperation *)_arDlingindex[i]).mi;
                            if (mm.downloadStatus == XLGDownloadStatusTypeFailed)
                                break;
                        }
                        i--;
                        i = MAX(0,i);
                        
                        __block NSUInteger nIndex = mi.serialNo;
                        mi.downloadStatus = XLGDownloadStatusTypeStop;
                        mi.serialNo = i;
                        
                        [o stopDownload];
                        
                        if(target != nil)
                            [o removeOperationDelegate:target];
                        else
                            [o removeAllOperationdelegate];
                        
                        [_arDlingindex removeObjectAtIndex:nIndex];
                        [_arDlingindex insertObject:o atIndex:i];
                        
                        [_commonindex modifyDownloadIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger serialNo,NSString* extendID,XLGDownloadStatusType status))
                        {
                            NSInteger nResult = FALSE;
                            for (; nIndex < _arDlingindex.count; nIndex++)
                            {
                                XLGDownloadIndex *mi = ((XLGDownloadOperation *)_arDlingindex[nIndex]).mi;
                                mi.serialNo = nIndex;
                                nResult =  modify(nIndex,mi.extendID,mi.downloadStatus);
                                if(nResult != YES)
                                    break;
                            }
                            return nResult;
                        }];
                        
                        [self exchangeDownloadItemStatus:mi];
                        
                        [arResult addObject:url];
                        
/*
#ifdef DEBUG
                        NSLog(@"stopdownload!!!--queueoperation--%i",[_queue operationCount]);
#endif
*/
                        break;
                    }
                }
            }
            if(completion != NULL)
                completion(arResult);
        }];
    });
}

-(void)stopDownload:(NSString*)szTag
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        if(szTag.length > 0)
        {
            if([szTag isEqualToString:HTTPDOWNLOADSUSPENDTAG] == YES)
            {
                NSUInteger len = _arDlingindex.count;
                for(NSUInteger i = 0; i < len; i++)
                {
                    XLGDownloadOperation * o = [[_arDlingindex[i] retain_mm] autorelease_mm];
                    XLGDownloadIndex* mi = o.mi;
                    if(XLGDownloadStatusTypeDownloading == mi.downloadStatus || XLGDownloadStatusTypeWaiting == mi.downloadStatus)
                    {
                        [o stopDownload];
                        
                        mi.downloadStatus = XLGDownloadStatusTypeNextContinue;
                        
                        [self exchangeDownloadItemStatus:mi];
                        
                        [_arDlingindex removeObjectAtIndex:mi.serialNo];
                        [_arDlingindex insertObject:o atIndex:mi.serialNo];
                    }
                }
                
                [_commonindex modifyDownloadIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger serialNo,NSString* extendID,XLGDownloadStatusType status))
                {
                    NSInteger nResult = FALSE;
                    for(XLGDownloadOperation* o in _arDlingindex)
                    {
                        XLGDownloadIndex* mi = o.mi;
                        if(XLGDownloadStatusTypeDownloading == mi.downloadStatus || XLGDownloadStatusTypeWaiting == mi.downloadStatus)
                        {
                            nResult = modify(mi.serialNo,mi.extendID,mi.downloadStatus);
                            if(nResult != YES)
                                break;
                        }
                    }
                    return nResult;
                }];
            }
        }
        else
        {
            for(XLGDownloadOperation* o in _arDlingindex)
            {
                XLGDownloadIndex* mi = o.mi;
                if(XLGDownloadStatusTypeDownloading == mi.downloadStatus || XLGDownloadStatusTypeWaiting == mi.downloadStatus)
                {
                    mi.downloadStatus = XLGDownloadStatusTypeNextContinue;
                    [o stopDownload];
                }
            }
            
            [_commonindex modifyDownloadIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger serialNo,NSString* extendID,XLGDownloadStatusType status))
            {
                NSInteger nResult = FALSE;
                for(XLGDownloadOperation* o in _arDlingindex)
                {
                    XLGDownloadIndex* mi = o.mi;
                    if(XLGDownloadStatusTypeDownloading == mi.downloadStatus || XLGDownloadStatusTypeWaiting == mi.downloadStatus)
                    {
                        nResult = modify(mi.serialNo,mi.extendID,mi.downloadStatus);
                        if(nResult != YES)
                            break;
                    }
                }
                return nResult;
            }];
        }
/*
#ifdef DEBUG
        for(XLGDownloadOperation* o in _arDlingindex)
        {
            CMessageInstanceObj* mi=o._mi;
            NSLog(@"stopdownload--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
        }
        
        NSMutableArray* ar=nil;
        [self getDownloadIndexs:EDownloadIndexTypeDOWNLOADING mi:&ar];
        for(CMessageInstanceObj* mi in ar)
            NSLog(@"databasestopdownload--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
        [ar release_mm];
        
        NSLog(@"stopdownload");
        NSLog(@"_downloadingRange.location:%d,_downloadingRange.length:%d",_downloadingRange.location,_downloadingRange.length);
        NSLog(@"_waitingRange.location:%d,_waitingRange.length:%d",_waitingRange.location,_waitingRange.length);
        NSLog(@"_stopRange.location:%d,_stopRange.length:%d",_stopRange.location,_stopRange.length);
        NSLog(@"_failedRange.location:%d,_failedRange.length:%d",_failedRange.location,_failedRange.length);
#endif
*/
    }];
}

- (void)enumDownloadingItem:(void (^)(NSUInteger nIndex, XLGDownloadIndex *downloadingItem, BOOL *bStop))downloadingItem
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        [_arDlingindex enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
        {
            XLGDownloadOperation *op = obj;
            downloadingItem(idx,[XLGDownloadIndex downloadIndexWithWithDownloadIndex:op.mi],stop);
        }];
    }];
}

- (void)enumDownloadManagerOperationDelegate:(void (^)(NSUInteger nIndex, id obj, BOOL *bStop))downloaduitarget
{
    [_operationDelegateQueue dispatchThreadSync:^
    {
        [_arOperationDelegate enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
        {
            downloaduitarget(idx,obj,stop);
        }];
    }];
}

//- (int)isDownloadIndexExist:(XLGDownloadTargetType)type
//{
//	int nResult=-1;
//	NSMutableArray* ar=nil;
//	nResult=[self getDownloadIndexs:type mi:&ar];
//	if(SQLITE_DONE==nResult)
//	{
//		nResult=ar.count>0?YES:NO;
//	}
//	return nResult;
//}

-(void)downloadOperation:(XLGDownloadOperation *)operation willFinishFileAssembly:(NSString *)file
{
    XLGDownloadIndex* mi = operation.mi;
    mi.downloadStatus = XLGDownloadStatusTypeWaitingFinish;
    [self exchangeDownloadItemStatus:mi];
}

-(void)downloadOperation:(XLGDownloadOperation *)operation didFinishFileAssembly:(NSString *)file
{
    
}

-(NSInteger)downloadOperation:(XLGDownloadOperation *)operation endType:(XLGDownloadEndType)type
{
    [_dlingIndexQueue dispatchThreadSync:^
    {
        [[operation retain_mm]autorelease_mm];
        
        XLGDownloadIndex* mi = operation.mi;
        
        switch(type)
        {
            case XLGDownloadEndTypeFinish:
            {
                mi.downloadStatus = XLGDownloadStatusTypeWaitingFinish;
                [self exchangeDownloadItemStatus:mi];
                    
          //          NSLog(@"ENG %@ %d %d",mi.m_szContent,mi.m_nReceiver,mi.m_nSender);
/*
#ifdef DEBUG
                    NSLog(@"downloadfinish!!!--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
#endif
*/
                __block NSUInteger nIndex = mi.serialNo;
                mi.downloadStatus = XLGDownloadStatusTypeFinished;
                mi.targetType = XLGDownloadTargetTypeFinished;
                mi.downloadTime = [NSDate date];
                
                [_commonindex modifyFinishDownloadIndex:mi.extendID];

                [_arDlingindex removeObjectAtIndex:nIndex];
                
                [_commonindex modifyDownloadIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger serialNo,NSString* extendID,XLGDownloadStatusType status))
                {
                     NSInteger nResult = FALSE;
                     for (; nIndex < _arDlingindex.count; nIndex++)
                     {
                         XLGDownloadIndex *mi = ((XLGDownloadOperation *)_arDlingindex[nIndex]).mi;
                         mi.serialNo = nIndex;
                         nResult =  modify(nIndex,mi.extendID,mi.downloadStatus);
                         if(nResult != YES)
                             break;
                     }
                     return nResult;
                }];
/*
 #ifdef DEBUG
                    for(XLGDownloadOperation* o in _arDlingindex)
                    {
                        CMessageInstanceObj* mi=o._mi;
                        NSLog(@"databasedownloadfinish--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
                    }
                    
                    NSMutableArray* ar=nil;
                    [self getDownloadIndexs:EDownloadIndexTypeDOWNLOADING mi:&ar];
                    for(CMessageInstanceObj* mi in ar)
                        NSLog(@"databasedownloadfinish--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
                    [ar release_mm];
                    
                    NSLog(@"databasedownloadfinish");
                    NSLog(@"_downloadingRange.location:%d,_downloadingRange.length:%d",_downloadingRange.location,_downloadingRange.length);
                    NSLog(@"_waitingRange.location:%d,_waitingRange.length:%d",_waitingRange.location,_waitingRange.length);
                    NSLog(@"_stopRange.location:%d,_stopRange.length:%d",_stopRange.location,_stopRange.length);
                    NSLog(@"_failedRange.location:%d,_failedRange.length:%d",_failedRange.location,_failedRange.length);
#endif
*/
                [self exchangeDownloadItemStatus:mi];
            
                DispatchMainThreadAsync(^
                {
                    [NSNotificationCenter postNotification:XLGDownloadManagerDownloadFinished userInfo:@{XLGDownloadManagerDownloadFinished:mi}];
                });
                
                break;
            }
            case XLGDownloadEndTypeError:
            {
/*
#ifdef DEBUG
                    NSLog(@"downloaderror!!!--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
#endif
*/
                __block NSUInteger nIndex = mi.serialNo;
                mi.serialNo = _arDlingindex.count - 1;
                mi.downloadStatus = XLGDownloadStatusTypeFailed;
                
                [_arDlingindex removeObjectAtIndex:nIndex];
                [_arDlingindex addObject:operation];
                
                [_commonindex modifyDownloadIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger serialNo,NSString* extendID,XLGDownloadStatusType status))
                {
                    NSInteger nResult = FALSE;
                    for (; nIndex < _arDlingindex.count; nIndex++)
                    {
                        XLGDownloadIndex *mi = ((XLGDownloadOperation *)_arDlingindex[nIndex]).mi;
                        mi.serialNo = nIndex;
                        nResult =  modify(nIndex,mi.extendID,mi.downloadStatus);
                        if(nResult != YES)
                            break;
                    }
                    return nResult;
                }];
/*
#ifdef DEBUG
                    for(XLGDownloadOperation* o in _arDlingindex)
                    {
                        CMessageInstanceObj* mi=o._mi;
                        NSLog(@"databasedownloaderror--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
                    }
                    
                    NSMutableArray* ar=nil;
                    [self getDownloadIndexs:EDownloadIndexTypeDOWNLOADING mi:&ar];
                    for(CMessageInstanceObj* mi in ar)
                        NSLog(@"databasedownloaderror--%i,%i,%@",mi.m_nStatus,mi.m_nReadstatus,mi.m_szTitle);
                    [ar release_mm];
                    
                    NSLog(@"databasedownloaderror");
                    NSLog(@"_downloadingRange.location:%d,_downloadingRange.length:%d",_downloadingRange.location,_downloadingRange.length);
                    NSLog(@"_waitingRange.location:%d,_waitingRange.length:%d",_waitingRange.location,_waitingRange.length);
                    NSLog(@"_stopRange.location:%d,_stopRange.length:%d",_stopRange.location,_stopRange.length);
                    NSLog(@"_failedRange.location:%d,_failedRange.length:%d",_failedRange.location,_failedRange.length);
#endif
*/
                [self exchangeDownloadItemStatus:mi];
            
                break;
            }
        }
    }];
    
        //    [self DownloadEndCategoryOpeation:mi Type:type];
        
    if([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
    {
        if([XMSBackgroundMaintain isBackgrounsService:XLGDownloadManagerBackgroundMaintainKey] && [self isNeedBackgroundMaintain] == NO)
            [XMSBackgroundMaintain backgroundTaskIsFinished:XLGDownloadManagerBackgroundMaintainKey];
    }
        
    return true;
}

//-(void)DownloadEndCategoryOpeation:(CMessageInstanceObj*)mi Type:(EDownloadEndType)type
//{
//
//}

- (void)deleteFinishedItemWithExtendIDs:(NSArray *)arExtendids asyncCompletion:(void(^)(NSArray *arResult))completion
{
    DispatchThread(^
    {
        if(arExtendids.count > 0)
        {
            NSMutableArray *arResult = [[NSMutableArray new]autorelease_mm];
            
            NSMutableArray *URLs = [[NSMutableArray new] autorelease_mm];
            [_commonindex getIndexWithExtendIDs:arExtendids completion:^(NSInteger nResult, NSArray *index)
            {
                for(XLGDownloadIndex *i in index)
                {
                    [URLs addObject:i.URL];
                }
            }];

            if(URLs.count > 0)
            {
                [_commonindex deleteIndexWithURLs:URLs];
                for(NSString* szUrl in URLs)
                {
                    NSString* fileName = [szUrl lastPathComponent];
                    [self deleteFile:fileName];
                    
                    [arResult addObject:szUrl];
                }
            }
            
            completion(arResult);
        }
        else
            completion(nil);
    });
}

- (void)deleteFinishedItemWithURLs:(NSArray *)arUrl asyncCompletion:(void(^)(NSArray *arResult))completion
{
    DispatchThread(^
    {
        if(arUrl.count >0)
        {
            NSMutableArray *arResult = [[NSMutableArray new]autorelease_mm];
            [_commonindex deleteIndexWithURLs:arUrl];
            for(NSString* szUrl in arUrl)
            {
                NSString* fileName = [szUrl lastPathComponent];
                [self deleteFile:fileName];
                
                [arResult addObject:szUrl];
            }
            
            completion(arResult);
        }
        else
            completion(arUrl);
    });
}

- (void)updateDownloadItem:(NSString *)extendID fileTotalByte:(NSUInteger)totalByte downloadByte:(NSUInteger)downloadByte
{
    [_commonindex updateDownloadItem:extendID fileTotalByte:totalByte downloadByte:downloadByte];
}

-(XLGDownloadOperation*)initDownloadOperationChannel:(XLGDownloadIndex*)mi
{
    XLGDownloadOperation* op = nil;
    switch(mi.channelType)
    {
        case XLGDownloadOperationChannelTypeSOCKET:
        {
            op = [[XLGDownloadSocketOperation alloc]initWithDownloadIndex:mi];
            break;
        }
        default:
        {
            op = [[XLGDownloadHttpOperation alloc]initWithDownloadIndex:mi];
            break;
        }
    }
    
    op.internalDelegate = self;
    
    return [op autorelease_mm];
}


- (BOOL)openDownloadFinishedFile:(NSString *)fileName withTitle:(NSString*)title presentedViewController:(UIViewController *)vcl
{
    return NO;
}

//-(NSString*)FsfileToMessageInstanceObjContent:(CFsfilesObj*)fsfile
//{
//    return [NSString stringWithFormat:@"%@/%@/%@",fsfile.m_szFileversion,fsfile.m_szFileid,fsfile.m_szFilename];
//}

- (NSString *)defaultStorePath
{
    return [[XLGContext context].m_szUserdefaulteppath stringByAppendingPathComponent:XLGDownloadDataFolder];
}

- (void)deleteFile:(NSString*)fileName
{
    [XMSFileHelper deleteFileDir:[[self defaultStorePath] stringByAppendingPathComponent:fileName]];
}

-(BOOL)isNeedBackgroundMaintain
{
    __block BOOL isNeed= NO;
    [_dlingIndexQueue dispatchThreadSync:^
    {
        for(XLGDownloadOperation* ho in _arDlingindex)
        {
            if(ho.mi.downloadStatus == XLGDownloadStatusTypeDownloading || ho.mi.downloadStatus == XLGDownloadStatusTypeWaiting)
            {
                isNeed =YES;
                break;
            }
        }
    }];
    return isNeed;
}

static XLGDownloadManager* s_downloadmanager;

+(void)initDownloadManager
{
	if(nil==s_downloadmanager)
	{
		s_downloadmanager=[XLGDownloadManager new];
		[s_downloadmanager initDownloadingIndexs];
	}
}

+(XLGDownloadManager*)downloadManager
{
    return s_downloadmanager;
}

+(void)releaseDownloadManager
{
    [s_downloadmanager releaseDownloadManager];
	[s_downloadmanager release_mm];
	s_downloadmanager=nil;
}

+ (void)suspendDownloadManager
{
    [s_downloadmanager suspendDownloadManager];
}

+ (BOOL)resumeDownloadManger
{
    return [s_downloadmanager resumeDownloadManger];
}

@end

@implementation XLGDownloadManager (TransferURL)

+(void)operateNeedTransferURLBlock:(NSString*(^)(NSString *URL))transferURL
{
    [XLGDownloadHttpOperation operateNeedTransferURLBlock:transferURL];
}

@end

